{
int width, height;
} saved_fullscreen, saved_maximized;
+
+ gboolean use_custom_surface;
};
struct _GdkWindowImplWaylandClass
GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
GdkWindow *transient_for;
- if (!impl->mapped)
+ if (!impl->mapped && !impl->use_custom_surface)
{
/* Popup menus can appear without a transient parent, which means they
* cannot be positioned properly on Wayland. This attempts to guess the
* surface they should be positioned with by finding the surface beneath
- * the device that created the grab for the popup window */
-
+ * the device that created the grab for the popup window
+ */
if (!impl->transient_for && impl->hint == GDK_WINDOW_TYPE_HINT_POPUP_MENU)
{
transient_for = gdk_device_get_window_at_position (impl->grab_device, NULL, NULL);
XSERVER_TIME_IS_LATER (display_wayland->user_time, impl->user_time))
gdk_wayland_window_set_user_time (window, impl->user_time);
- impl->surface = wl_compositor_create_surface(display_wayland->compositor);
- wl_surface_set_user_data(impl->surface, window);
+ if (!impl->surface)
+ {
+ impl->surface = wl_compositor_create_surface(display_wayland->compositor);
+ wl_surface_set_user_data(impl->surface, window);
+ }
- impl->shell_surface = wl_shell_get_shell_surface (display_wayland->shell,
- impl->surface);
- wl_shell_surface_add_listener(impl->shell_surface,
- &shell_surface_listener, window);
+ if (!impl->use_custom_surface && display_wayland->shell)
+ {
+ impl->shell_surface = wl_shell_get_shell_surface (display_wayland->shell,
+ impl->surface);
+ wl_shell_surface_add_listener(impl->shell_surface,
+ &shell_surface_listener, window);
+ }
- gdk_window_set_type_hint (window, impl->hint);
+ gdk_window_set_type_hint (window, impl->hint);
_gdk_make_event (window, GDK_MAP, NULL, FALSE);
event = _gdk_make_event (window, GDK_VISIBILITY_NOTIFY, NULL, FALSE);
{
if (impl->shell_surface)
wl_shell_surface_destroy(impl->shell_surface);
- if (impl->surface)
- wl_surface_destroy(impl->surface);
+ if (impl->use_custom_surface)
+ {
+ wl_surface_attach (impl->surface, NULL, 0, 0);
+ wl_surface_commit (impl->surface);
+ }
+ else if (impl->surface)
+ {
+ wl_surface_destroy(impl->surface);
+ impl->surface = NULL;
+ }
impl->shell_surface = NULL;
- impl->surface = NULL;
cairo_surface_destroy(impl->server_surface);
impl->server_surface = NULL;
impl->mapped = FALSE;
{
if (impl->shell_surface)
wl_shell_surface_destroy(impl->shell_surface);
- if (impl->surface)
- wl_surface_destroy(impl->surface);
+ if (impl->use_custom_surface)
+ {
+ wl_surface_attach (impl->surface, NULL, 0, 0);
+ wl_surface_commit (impl->surface);
+ }
+ else if (impl->surface)
+ {
+ wl_surface_destroy(impl->surface);
+ impl->surface = NULL;
+ }
impl->shell_surface = NULL;
- impl->surface = NULL;
cairo_surface_destroy(impl->server_surface);
impl->server_surface = NULL;
impl->mapped = FALSE;
if (impl->fullscreen)
return;
+ if (!impl->shell_surface)
+ return;
+
impl->saved_fullscreen.width = gdk_window_get_width (window);
impl->saved_fullscreen.height = gdk_window_get_height (window);
+
wl_shell_surface_set_fullscreen (impl->shell_surface,
WL_SHELL_SURFACE_FULLSCREEN_METHOD_DEFAULT,
0,
if (!impl->fullscreen)
return;
+ if (!impl->shell_surface)
+ return;
+
wl_shell_surface_set_toplevel (impl->shell_surface);
gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0);
gdk_wayland_window_configure (window,
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+ if (!impl->shell_surface)
+ return;
+
wl_shell_surface_resize (impl->shell_surface,
gdk_wayland_device_get_wl_seat (device),
_gdk_wayland_display_get_serial (wayland_display),
impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+ if (!impl->shell_surface)
+ return;
+
wl_shell_surface_move (impl->shell_surface,
gdk_wayland_device_get_wl_seat (device),
_gdk_wayland_display_get_serial (wayland_display));
return impl->shell_surface;
}
+
+/**
+ * gdk_wayland_window_set_use_custom_surface:
+ * @window: (type GdkWaylandWindow): a #GdkWindow
+ *
+ * Marks a #GdkWindow as a custom Wayland surface. The application is
+ * expected to register the surface as some type of surface using
+ * some Wayland interface.
+ *
+ * Agood example would be writing a panel or on-screen-keyboard as an
+ * out-of-process helper - as opposed to having those in the compositor
+ * process. In this case the underlying surface isn't a wl_shell
+ * surface and the panel or OSK client need to identify the wl_surface
+ * as a panel or OSK to the compositor. The assumption is that the
+ * compositor will expose a private interface to the special client
+ * that lets the client identify the wl_surface as a panel or such.
+ *
+ * This function should be called before a #GdkWindow is shown. This is
+ * best done by connecting to the #GtkWidget::realized signal:
+ *
+ * <informalexample>
+ * <programlisting>
+ * static void
+ * widget_realize_cb (GtkWidget *widget)
+ * {
+ * GdkWindow *window;
+ * struct wl_surface *surface;
+ * struct input_panel_surface *ip_surface;
+ *
+ * window = gtk_widget_get_window (widget);
+ * gdk_wayland_window_set_custom_surface (window);
+ *
+ * surface = gdk_wayland_window_get_wl_surface (window);
+ * ip_surface = input_panel_get_input_panel_surface (input_panel, surface);
+ * input_panel_surface_set_panel (ip_surface);
+ * }
+ *
+ * static void
+ * setup_window (GtkWindow *window)
+ * {
+ * g_signal_connect (window, "realize", G_CALLBACK (widget_realize_cb), NULL);
+ * }
+ * </programlisting>
+ * </informalexample>
+ *
+ * Since: 3.10
+ */
+void
+gdk_wayland_window_set_use_custom_surface (GdkWindow *window)
+{
+ GdkWindowImplWayland *impl;
+ GdkWaylandDisplay *display;
+
+ g_return_if_fail (GDK_IS_WAYLAND_WINDOW (window));
+
+ impl = GDK_WINDOW_IMPL_WAYLAND (window->impl);
+
+ if (!impl->surface)
+ {
+ display = GDK_WAYLAND_DISPLAY (gdk_window_get_display (window));
+ impl->surface = wl_compositor_create_surface (display->compositor);
+ wl_surface_set_user_data (impl->surface, window);
+ }
+
+ impl->use_custom_surface = TRUE;
+}